#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#define MAX_PACKET_SIZE 1500

// QUEUE ELEMENT STRUCTURE
typedef struct Element
{
    char data[MAX_PACKET_SIZE];
    int size;

} Element;

// EMULATOR PACKET STRUCTURE
typedef struct Queue
{
    int front;    // Is the index of the next element to be removed
    int back;     // Is the index of the next open location in queue
    int size;
    int space_left;

    Element elements[];

} Queue;

Queue* init_queue(Queue *queue, int size)
{
    queue = malloc(sizeof(Queue) + size * sizeof(Element));
    queue->front = 0;
    queue->back = 0;
    queue->size = size;
    queue->space_left = size;

    // Fill the array as empty
    int i;
    for(i = 0; i < queue->size; i++)
    {
        queue->elements[i].size = -1;
    }

    return queue;
}

void delete_queue(Queue *queue)
{
    free(queue);
}

// return -1 if error, 0 if success
int enqueue(Queue *queue, char *data, int length)
{
    // If no space is left in the queue
    if (queue->space_left <= 0)
    {
        return -1;
    }

    memcpy(queue->elements[queue->back].data, data, length);
    queue->elements[queue->back].size = length;
    queue->space_left--;

    // Manage index ptr
    if (queue->back == (queue->size - 1))
    {
        queue->back = 0;
    }
    else
    {
        queue->back++;
    }

    return 0;
}

// return -1 if error, size of dequeued element if success
// Will fill data with dequeued element
int dequeue(Queue *queue, char *data, int length)
{
    int return_length = 0;

    // Check if the queue is empty
    if (queue->space_left == queue->size)
    {
        return -1;
    }

    // No room to memcpy in provided buffer
    if (queue->elements[queue->front].size > length)
    {
        return -1;
    }

    printf("SPACE LEFT: %d\n", queue->space_left);

    memcpy(data, queue->elements[queue->front].data, queue->elements[queue->front].size);
    return_length = queue->elements[queue->front].size;
    queue->elements[queue->front].size = -1;
    queue->space_left++;


    // Manage index ptr
    if (queue->front == (queue->size - 1))
    {
        queue->front = 0;
    }
    else
    {
        queue->front++;
    }

    return return_length;
}

void dump_queue(Queue *queue)
{
    printf("STATUS OF QUEUE:\n> front:\t%d\n> back:\t\t%d\n> size:\t\t%d\n> space_left:\t%d\n", queue->front, queue->back, queue->size, queue->space_left);

    int i;
    for(i = 0; i < queue->size; i++)
    {
        printf("Element #%d: size = %d\n", i, queue->elements[i].size);
    }
}
